package libcore.net.callback;

import androidx.annotation.Nullable;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import libcore.base.Result;
import libcore.config.LibConfig;
import libcore.config.LogUtil;
import libcore.util.ToastUtil;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.HttpException;
import retrofit2.Response;

/**
 * 创建时间：2016年10月10日13:43 <br>
 * 作者：jaaksi <br>
 * 描述：retrofit callback 简易实现类
 * 要考虑好cancel的情景
 */
public abstract class SimpleCallback<T> implements Callback<T> {
  private static final String TAG = "SimpleCallback";

  private boolean mIsSuccess;
  private boolean mHasData;

  @Override
  public final void onResponse(Call<T> call, Response<T> response) {
    // 处理call被cancel的情况
    if (call != null && call.isCanceled()) {
      onCanceled(call, null);
      LogUtil.e(LibConfig.TAG_HTTP, call.request().url().toString() + " cancel");
      return;
    }

    T entity = response.body();
    if (entity != null && entity instanceof Result) {
      Result result = (Result) entity;
      mIsSuccess = result.isSuccess();
      mHasData = result.hasData();
    }
    onResponse(entity, call);
  }

  @Override
  public final void onFailure(Call<T> call, Throwable t) {
    if (t != null) {
      LogUtil.e(TAG, "api:" + call.request().url().toString() + "\n" + t.getMessage());
      if (LibConfig.isDebug()) {
        ToastUtil.toast(t.getMessage());
      }
    }
    // 处理call被cancel的情况
    if (call != null && call.isCanceled()) {
      onCanceled(call, t);
      LogUtil.e(LibConfig.TAG_HTTP, call.request().url().toString() + " cancel");
      return;
    }

    if (isNetException(t)) {
      //      mIsSuccess = false;
      onNetworkError(call, t);
    } else {
      onResponse(null, call);
    }
  }

  protected void onCanceled(Call<T> call, @Nullable Throwable t) {
  }

  private boolean isNetException(Throwable t) {
    return t instanceof UnknownHostException || t instanceof SocketTimeoutException ||
      t instanceof ConnectException || t instanceof HttpException;
  }

  /** 网络异常 */
  public void onNetworkError(Call<T> call, Throwable t) {
    onResponse(null, call);
  }

  public abstract void onResponse(T entity, Call<T> call);

  protected final boolean isSuccess() {
    return mIsSuccess;
  }

  protected final boolean hasData() {
    return mHasData;
  }
}
